﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace MDF
{
    class IO_ini
    {
        //声明读写ini文件的api函数
        /// <summary>
        /// 写入键和值
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="key">Key名称</param>
        /// <param name="value">写入值</param>
        /// <param name="filePath">ini文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileString(string section, string key, string value, string filePath);
        /// <summary>
        /// 读单个值
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="key">Key名称</param>
        /// <param name="def">读取失败时的默认值</param>
        /// <param name="valueBuffer">读取的内容缓冲区，\0 时终止</param>
        /// <param name="size">内容缓冲区的长度</param>
        /// <param name="filePath">ini文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder valueBuffer, int size, string filePath);
        /// <summary>
        /// 读多个值（用来读多个Key值）
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="key">Key名称</param>
        /// <param name="def">读取失败时的默认值</param>
        /// <param name="valueBuffer">读取的内容缓冲区，读取之后，多余的地方使用\0填充</param>
        /// <param name="size">内容缓冲区的长度</param>
        /// <param name="filePath">ini文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string section, string key, string def, [In, Out] char[] valueBuffer, uint size, string filePath);
        /// <summary>
        /// 获取某个指定节点(Section)中所有KEY和Value
        /// </summary>
        /// <param name="section">节点名称</param>
        /// <param name="lpReturnedString">返回值的内存地址,每个之间用\0分隔</param>
        /// <param name="nSize">内存大小(characters)</param>
        /// <param name="filePath">ini文件路径</param>
        /// <returns>内容的实际长度,为0表示没有内容,为nSize-2表示内存大小不够</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSection(string section, IntPtr lpReturnedString, uint nSize, string filePath);



        private string iniPath;
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="Path"></param>
        public IO_ini(string Path)
        {
            iniPath = Path;
            Create_IniFile();
        }

        /// <summary>
        /// 创建ini文件，不存在时才创建
        /// </summary>
        private void Create_IniFile()
        {
            try
            {
                if (!File.Exists(iniPath))//判断是否存在
                {
                    //不存在就创建
                    FileStream fileStream = new FileStream(iniPath, FileMode.CreateNew);
                    fileStream.Close();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 写、改、删 ini
        /// </summary>
        /// <param name="Section">节点</param>
        /// <param name="Key">键</param>
        /// <param name="Value">值</param>
        public void IniWriteValue(string Section, string Key, string Value)
        {
            WritePrivateProfileString(Section, Key, Value, iniPath);
        }
        /// <summary>
        /// 读ini单个键值
        /// </summary>
        /// <param name="Section">节点</param>
        /// <param name="Key">键</param>
        /// <returns></returns>
        public string IniReadValue(string Section, string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            GetPrivateProfileString(Section, Key, "", temp, 255, iniPath);
            return temp.ToString();
        }
        /// <summary>
        /// 读ini指定节点的所有Key
        /// </summary>
        /// <param name="Section">节点</param>
        /// <returns></returns>
        public string[] IniReadKeys(string Section)
        {
            string[] keys = new string[0]; 
            const int size = 1024 * 10;
            if (string.IsNullOrEmpty(Section))
            {
                throw new ArgumentException("必须指定节点名称", "section");
            }
            char[] chars = new char[size];
            uint bytesReturned = GetPrivateProfileString(Section, null, null, chars, size, iniPath);
            if (bytesReturned != 0)
            {
                keys = new string(chars).Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }
            chars = null;
            return keys;
        }

        /// <summary>
        /// 获取INI文件中指定节点(Section)中的所有条目,并返回 Dictionary 对象
        /// </summary>
        /// <param name="Section">节点</param>
        /// <returns></returns>
        public Dictionary<string, string> GetSectionDic(string Section)
        {
            uint MAX_BUFFER = 32767;
            string[] items = new string[0];
            //分配内存
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
            uint bytesReturned = GetPrivateProfileSection(Section, pReturnedString, MAX_BUFFER, iniPath);
            if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))

            {
                string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
                items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }
            Marshal.FreeCoTaskMem(pReturnedString);     //释放内存
            
            if (items == null) //无结果返回空
            {
                return null;
            }
            Dictionary<string, string> dic = new Dictionary<string, string>();
            foreach (string item in items)
            {
                if (!item.Contains("="))
                {
                    continue;
                }
                string[] part = item.Split('=');
                dic.Add(part[0], part[1]);
            }
            return dic;
        }
    }
}
